/*
* FaceCat的Flutter框架
* 上海卷卷猫信息技术有限公司
*/

import 'package:flutter/material.dart';
import 'dart:math';
import 'dart:async';
import 'facecat.dart';

FCPaint gPaint = FCPaint();

/*
* 面积图数据
*/
class PyrometerData{
    String text = ""; //数值
    String key = ""; //键
    double lastClose = 0; //开始数据
    double close = 0; //最新数据
    double value = 0; //数值
    FCPoint location = FCPoint(0, 0); //位置
    FCSize size = FCSize(0, 0); //大小
}

/*
* 面积图
*/
class PyrometerDiv extends FCView{
    bool useAnimation = false; //是否使用动画
    double INF = 0x3f3f3f; //无效数据
    double Rwidth = 0; //宽度
    double Rheight = 0; //高度
    List<PyrometerData> children = <PyrometerData>[]; //子视图
    List<FCRect> rects = <FCRect>[];
    PyrometerDiv() {
        viewType = "pyrometer";
    }
}

/*
* 获取主绘图单元
*/
FCPaint getMainPaint(){
  if(!gPaint.hasLoadEvent){
    gPaint.addLoadEvent(onLoad);
  }
  return gPaint;
}

/*
* 重绘背景的实现方法
* view:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
void onPaint(FCView view, FCPaint paint, FCRect clipRect) {
    if (view.viewType == "pyrometer"){
        PyrometerDiv pView = view as PyrometerDiv;
        drawDiv(view, paint, clipRect);
        for (int i = 0; i < pView.children.length; i++){
            PyrometerData pData = pView.children[i];
            String backColor = "none";
            String borderColor = "none";
            if (paint.defaultUIStyle == "dark"){
                if (pData.close >= pData.lastClose){
                    backColor = "rgb(219,68,83)";
                }
                else{
                    backColor = "rgb(15,193,118)";
                }
                borderColor = "rgb(0,0,0)";
            }
            else if (paint.defaultUIStyle == "light"){
                if (pData.close >= pData.lastClose){
                    backColor = "rgb(255,255,255)";
                }
                else{
                    backColor = "rgb(255,255,255)";
                }
                borderColor = "rgb(255,255,255)";
            }
            paint.fillRect(backColor, pData.location.x, pData.location.y, pData.location.x + pData.size.cx, pData.location.y + pData.size.cy);
            paint.drawRect(borderColor, 1, 0, pData.location.x, pData.location.y, pData.location.x + pData.size.cx, pData.location.y + pData.size.cy);
            double fontSize1 = (min(pData.size.cx, pData.size.cy) / 5);
            if (fontSize1 > 1){
                String baseUpper = pData.text;
                String font1 = "Default," + fontSize1.toString();
                FCSize tSize = paint.textSize(baseUpper, font1);
                bool isContinue = false;
                while (tSize.cx > pData.size.cx - 10){
                    fontSize1 = fontSize1 - 1;
                    if (fontSize1 < 2){
                        isContinue = true;
                        break;
                    }
                    font1 = "Default," + fontSize1.toString();
                    tSize = paint.textSize(baseUpper, font1);
                }
                if (isContinue){
                    continue;
                }
                String quoteUpper = pData.key;
                String font2 = "Default," + (fontSize1 / 2).toString();
                FCSize tSize2 = paint.textSize(quoteUpper, font2);
                if (paint.defaultUIStyle == "dark"){
                    paint.drawText(baseUpper, "rgb(255,255,255)", font1, pData.location.x + (pData.size.cx - tSize.cx) / 2, pData.location.y + pData.size.cy / 2 - tSize.cy - tSize.cy / 2);
                    paint.drawText(quoteUpper, "rgb(255,255,255)", font2, pData.location.x + (pData.size.cx - tSize2.cx) / 2, pData.location.y + pData.size.cy / 2 - tSize.cy / 4);
                }
                else if (paint.defaultUIStyle == "light"){
                    paint.drawText(baseUpper, "rgb(0,0,0)", font1, pData.location.x + (pData.size.cx - tSize.cx) / 2, pData.location.y + pData.size.cy / 2 - tSize.cy - tSize.cy / 2);
                    paint.drawText(quoteUpper, "rgb(0,0,0)", font2, pData.location.x + (pData.size.cx - tSize2.cx) / 2, pData.location.y + pData.size.cy / 2 - tSize.cy / 4);
                }
                String strPrice = "0.00%";
                if(pData.lastClose > 0){
                    strPrice = (100 * (pData.close - pData.lastClose) / pData.lastClose).toStringAsFixed(2) + "%";
                    if(pData.close > pData.lastClose){
                        strPrice = "+" + strPrice;
                    }
                }
                String font3 = "Default," + (fontSize1 * 2 / 3).toString();
                FCSize tSize5 = paint.textSize(strPrice, font3);
                if (paint.defaultUIStyle == "dark"){
                    paint.drawText(strPrice, "rgb(255,255,255)", font3, pData.location.x + (pData.size.cx - tSize5.cx) / 2, pData.location.y + pData.size.cy / 2 + tSize.cy - tSize.cy / 2);
                }else if (paint.defaultUIStyle == "light"){
                    paint.drawText(strPrice, "rgb(0,0,0)", font3, pData.location.x + (pData.size.cx - tSize5.cx) / 2, pData.location.y + pData.size.cy / 2 + tSize.cy - tSize.cy / 2);
                }
            }
        }
    }
    else{
        onPaintDefault(view, paint, clipRect);
    }
}

/*
* 获取长度
*/
double rWidth(PyrometerDiv pyrometer, List<double> R, double w){
    return min(pyrometer.Rwidth, pyrometer.Rheight);
}

/*
* 获取最差的值
*/
double worst(PyrometerDiv pyrometer, List<double> R, double w){
    if (!R.isNotEmpty){
        return pyrometer.INF;
    }
    double rmx = 0.0;
    double rmn = pyrometer.INF;
    double s = 0.0;
    for (int x = 0; x < R.length; x++){
        double r = R[x];
        s = s + r;
        if (r > rmx){
            rmx = r;
        }
        if (r < rmn){
            rmn = r;
        }
    }
    double pw = pow(w, 2).toDouble();
    double sw = pow(s, 2).toDouble();
    return max(pw * rmx / sw, sw / (pw * rmn));
}

/*
* 重置行
*/
void layoutrow(PyrometerDiv pyrometer, List<double> R, double w){
    double width = pyrometer.size.cx;
    double height = pyrometer.size.cy;
    double lx = width - pyrometer.Rwidth;
    double ly = height - pyrometer.Rheight;
    int direction = 0;  
    
    double sumValue = 0.0;
    for (int x = 0; x < R.length; x++){
        sumValue = sumValue + R[x];
    }
    double ext = sumValue / w;
    if ((w - pyrometer.Rwidth).abs() <= 1e-6){
        pyrometer.Rheight = pyrometer.Rheight - ext;
        direction = 0;
    }else{
        pyrometer.Rwidth = pyrometer.Rwidth - ext;
        direction = 1;
    }
    for (int x = 0; x < R.length; x++){
        double r = R[x];
        if (direction == 0){
            double hh = ext;
            double ww = r / ext;
            FCRect newRect = FCRect(0, 0, 0, 0);
            newRect.left = lx.floor().toDouble();
            newRect.top = ly.floor().toDouble();
            newRect.right = (lx + ww).ceil().toDouble();
            newRect.bottom = (ly + hh).ceil().toDouble();
            pyrometer.rects.add(newRect);
            lx = lx + ww;
        }else{
            double ww = ext;
            double hh = r / ext;
            FCRect newRect = FCRect(0, 0, 0, 0);
            newRect.left = lx.floor().toDouble();
            newRect.top = ly.floor().toDouble();
            newRect.right = (lx + ww).ceil().toDouble();
            newRect.bottom = (ly + hh).ceil().toDouble();
            pyrometer.rects.add(newRect);
            ly = ly + hh;
        }
    }
}

/*
* 秒表事件
*/
void onPyrometerTime(PyrometerDiv pyrometer){
    var paint2 = false;
    if (pyrometer.useAnimation){
        for(int i = 0; i < pyrometer.rects.length; i++){
            PyrometerData subView = pyrometer.children[i];
            FCRect targetRect = pyrometer.rects[i];
            FCRect nowRect = FCRect(subView.location.x, subView.location.y, subView.location.x + subView.size.cx, subView.location.y + subView.size.cy);
            if (true) {
                if (nowRect.left > targetRect.left) {
                    nowRect.left -= (nowRect.left - targetRect.left) / 4;
                    if (nowRect.left - targetRect.left < 10) {
                        nowRect.left = targetRect.left;
                    }
                    paint2 = true;
                }
                else if (nowRect.left < targetRect.left) {
                    nowRect.left += (targetRect.left - nowRect.left) / 4;
                    if (targetRect.left - nowRect.left < 10) {
                        nowRect.left = targetRect.left;
                    }
                    paint2 = true;
                }
            }
            
            if (true) {
                if (nowRect.top > targetRect.top) {
                    nowRect.top -= (nowRect.top - targetRect.top) / 4;
                    if (nowRect.top - targetRect.top < 10) {
                        nowRect.top = targetRect.top;
                    }
                    paint2 = true;
                }
                else if (nowRect.top < targetRect.top) {
                    nowRect.top += (targetRect.top - nowRect.top) / 4;
                    if (targetRect.top - nowRect.top < 10) {
                        nowRect.top = targetRect.top;
                    }
                    paint2 = true;
                }
            }
            
            if (true) {
                if (nowRect.right > targetRect.right) {
                    nowRect.right -= (nowRect.right - targetRect.right) / 4;
                    if (nowRect.right - targetRect.right < 10) {
                        nowRect.right = targetRect.right;
                    }
                    paint2 = true;
                }
                else if (nowRect.right < targetRect.right) {
                    nowRect.right += (targetRect.right - nowRect.right) / 4;
                    if (targetRect.right - nowRect.right < 10) {
                        nowRect.right = targetRect.right;
                    }
                    paint2 = true;
                }
            }
            if (true) {
                if (nowRect.bottom > targetRect.bottom) {
                    nowRect.bottom -= (nowRect.bottom - targetRect.bottom) / 4;
                    if (nowRect.bottom - targetRect.bottom < 10) {
                        nowRect.bottom = targetRect.bottom;
                    }
                    paint2 = true;
                }
                else if (nowRect.bottom < targetRect.bottom) {
                    nowRect.bottom += (targetRect.bottom - nowRect.bottom) / 4;
                    if (targetRect.bottom - nowRect.bottom < 10) {
                        nowRect.bottom = targetRect.bottom;
                    }
                    paint2 = true;
                }
            }
            subView.location = FCPoint(nowRect.left, nowRect.top);
            subView.size = FCSize(nowRect.right - nowRect.left, nowRect.bottom - nowRect.top);
        }
    }else{
        for(int i = 0; i < pyrometer.rects.length; i++){
            PyrometerData subView = pyrometer.children[i];
            FCRect targetRect = pyrometer.rects[i];
            subView.location = FCPoint(targetRect.left, targetRect.top);
            subView.size = FCSize(targetRect.right - targetRect.left, targetRect.bottom - targetRect.top);
        }
    }
    if (paint2){
        invalidateView(pyrometer);
    }
}

/*
* 更新面积图
*/
void updatePyromoter(PyrometerDiv pyrometer){
    pyrometer.rects = <FCRect>[];
    double totalAmount = 0.0;
    for (int i = 0; i < pyrometer.children.length; i++){
        totalAmount += pyrometer.children[i].value;
    }
    List<double> rates = <double>[];
    for (int i = 0; i < pyrometer.children.length; i++){
        rates.add(pyrometer.children[i].value / totalAmount);
    }
    pyrometer.Rwidth = pyrometer.size.cx;
    pyrometer.Rheight = pyrometer.size.cy;
    List<double> areas = <double>[];
    for(int i = 0; i < rates.length; i++){
        areas.add(rates[i] * pyrometer.size.cx * pyrometer.size.cy);
    }
    List<double> children = areas;
    List<double> row = <double>[];
    double w = min(pyrometer.Rwidth, pyrometer.Rheight);
    while (true) {
        if (pyrometer.rects.length > pyrometer.children.length) {
            break;
        }
        if (w <= 0){
            break;
        }
        if (children.length == 0) {
            if (row.length > 0) {
                layoutrow(pyrometer, row, w);
            }
            break;
        }
        
        double c = children[0];
        if (c == 0){
            layoutrow(pyrometer, row, w);
            break;
        }
        List<double> newrow = <double>[];
        for (int x = 0; x < row.length; x++){
            newrow.add(row[x]);
        }
        newrow.add(c);
        if (worst(pyrometer, row, w) >= worst(pyrometer, newrow, w)) {
            List<double> tmp = <double>[];
            for (int x = 1; x < children.length; x++){
                tmp.add(children[x]);
            }
            children = tmp;
            row = newrow;
        }
        else {
            layoutrow(pyrometer, row, w);
            row = <double>[];
            w = rWidth(pyrometer, row, w.toInt().toDouble());
        }
    }
}

/*
* 更新悬浮状态
* views:视图集合
*/
void updateView(List<FCView> views) {
    updateViewDefault(views);
    for(int i = 0; i < views.length; i++){
        FCView view = views[i];
        if (view.viewType == "pyrometer"){
            updatePyromoter(view as PyrometerDiv);
            onPyrometerTime(view as PyrometerDiv);
        }
    }
}

/*
* 加载回调
*/
void onLoad(FCPaint paint){
  paint.defaultUIStyle = "dark";
  paint.size = FCSize(800, 600);
  paint.addPaintEvent(onPaint);
  paint.addUpdateViewEvent(updateView);
  PyrometerDiv pyrometer = PyrometerDiv();
  pyrometer.dock = "fill";
  pyrometer.backColor = "rgb(0,0,0)";
  addView(pyrometer, paint);
  String result = "600000.SH,浦发银行,8.530000,8.600000,8.410000,8.410000,39120100.000000,334119265.000000,8.380000,29352177375.000000,250373999999.999970,4.640000,1.160000,0.130000,9.220000,7.540000,2024-08-09 15:00:00\r\n600004.SH,XD白云机,9.380000,9.500000,9.380000,9.500000,8033400.000000,75759537.000000,9.450000,2366718283.000000,22200000000.000000,29.580000,0.860000,0.340000,10.400000,8.510000,2024-08-09 15:00:00\r\n600006.SH,东风股份,6.780000,6.990000,6.780000,6.830000,35222400.000000,241283922.000000,6.810000,2000000000.000000,13560000000.000000,24.190000,0.430000,1.760000,7.490000,6.130000,2024-08-09 15:00:00\r\n600007.SH,中国国贸,21.550000,21.800000,21.270000,21.390000,1336100.000000,28895121.000000,21.370000,1007282534.000000,21707000000.000000,16.120000,0.870000,0.130000,23.510000,19.230000,2024-08-09 15:00:00\r\n600008.SH,首创环保,2.900000,2.920000,2.900000,2.920000,29774500.000000,86571613.000000,2.910000,7340590677.000000,21288000000.000000,14.720000,0.550000,0.410000,3.200000,2.620000,2024-08-09 15:00:00\r\n600009.SH,上海机场,34.000000,34.580000,34.000000,34.460000,4586600.000000,157069239.000000,34.310000,2488481340.000000,65516999999.999992,54.830000,0.630000,0.240000,37.740000,30.880000,2024-08-09 15:00:00\r\n600010.SH,包钢股份,1.440000,1.460000,1.440000,1.460000,57457700.000000,83252242.000000,1.450000,45404942248.000000,45356000000.000000,256.900000,0.420000,0.180000,1.600000,1.310000,2024-08-09 15:00:00\r\n600011.SH,华能国际,7.390000,7.490000,7.390000,7.450000,44366300.000000,329906066.000000,7.430000,15698093359.000000,81273000000.000000,7.780000,0.580000,0.400000,8.170000,6.690000,2024-08-09 15:00:00\r\n600012.SH,皖通高速,14.660000,14.980000,14.620000,14.890000,2827100.000000,41627559.000000,14.800000,1658610000.000000,17088000000.000000,13.220000,0.340000,0.240000,16.280000,13.320000,2024-08-09 15:00:00\r\n600015.SH,华夏银行,6.180000,6.240000,6.150000,6.180000,22860300.000000,141797079.000000,6.170000,15914928468.000000,95093000000.000000,4.170000,0.820000,0.150000,6.790000,5.550000,2024-08-09 15:00:00\r\n600016.SH,民生银行,3.440000,3.470000,3.440000,3.440000,107261000.000000,370375560.000000,3.440000,43782418502.000000,121990000000.000020,2.800000,0.760000,0.300000,3.780000,3.100000,2024-08-09 15:00:00\r\n600017.SH,日照港,2.820000,2.840000,2.810000,2.830000,17684100.000000,49952132.000000,2.830000,3075653888.000000,8673000000.000000,11.760000,0.660000,0.570000,3.110000,2.550000,2024-08-09 15:00:00\r\n600018.SH,上港集团,6.020000,6.080000,6.000000,6.070000,15741500.000000,94885855.000000,6.060000,23284144750.000000,139506000000.000000,9.480000,0.660000,0.070000,6.670000,5.450000,2024-08-09 15:00:00\r\n600019.SH,宝钢股份,6.350000,6.420000,6.350000,6.380000,49714800.000000,317318548.000000,6.380000,21985240734.000000,138798000000.000000,18.120000,0.680000,0.230000,7.020000,5.740000,2024-08-09 15:00:00\r\n600020.SH,中原高速,3.750000,3.790000,3.740000,3.770000,7367200.000000,27735967.000000,3.770000,2247371832.000000,8428000000.000000,7.420000,0.550000,0.330000,4.150000,3.390000,2024-08-09 15:00:00\r\n600021.SH,上海电力,8.910000,9.100000,8.900000,9.060000,19713500.000000,176615040.000000,9.030000,2816743645.000000,23319000000.000000,9.900000,0.950000,0.750000,9.930000,8.130000,2024-08-09 15:00:00";
  List<String> strs = result.split("\r\n");
  for(int i = 1; i < strs.length; i++){
      List<String> subStrs = strs[i].split(",");
      if(subStrs.length >= 15){
        PyrometerData pData = PyrometerData();
        pData.key = subStrs[0];
        pData.text = subStrs[1];
        pData.value = double.parse(subStrs[6]);
        pData.close = double.parse(subStrs[2]);
        pData.lastClose = double.parse(subStrs[8]); 
        pData.size = FCSize(0, 0);
        pData.location = FCPoint(pyrometer.size.cx, pyrometer.size.cy);
        pyrometer.children.add(pData);
      }
  }
  pyrometer.children.sort((a, b) => b.value
                          .compareTo(a.value));
    updateView(paint.views);
    invalidateView(pyrometer);
}

void main() {
  runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    home: FCPage()
  ));
}


